﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Reflection;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Configuration;
using GrayParrot.Configuration;
using GrayParrot.Web.Security.Configuration;
using System.Threading;
using System.IO;
//using System.Transactions;

namespace GrayParrot.Web.Security
{
    public class PageBase : System.Web.UI.Page
    {
        private System.Security.Principal.IPrincipal m_user = null;
        private string m_pageName = string.Empty;
        private Guid m_pageId = Guid.Empty;

        public PageBase()
        {
            m_user = HttpContext.Current.User;
        }

        protected override void OnPreInit(EventArgs e)
        {
            ConfigurationManagerHelper cfgMgr = new ConfigurationManagerHelper();

            // check if the page is marked with Authorization Attribute...
            //var atts = Attribute.GetCustomAttributes(this.GetType(), typeof(AuthorizationAttribute))
            //                    .Cast<AuthorizationAttribute>()
            //                    .ToArray();

            //m_pageId = Guid.Parse(atts[0].PageId);
            m_pageName = System.IO.Path.GetFileNameWithoutExtension(Request.Url.AbsolutePath);

            //bool m_userNameWithoutDomain = GrayParrotSettings.GetConfiguration(@"GrayParrotGroup/GrayParrotSettings").UserNameWithoutDomain;

            string m_username = string.Empty;
            if (cfgMgr.GetUserNameWithoutDomain())
            {
                m_username = m_user.Identity.Name.Split('\\')[1];
            }
            else
            {
                m_username = m_user.Identity.Name;
            }

            if (string.IsNullOrWhiteSpace(m_username))
            {
                // anonymous enabled
                if (!cfgMgr.GetNoLoginRequired())
                {
                    // login required...
                    string m_loginUrl = cfgMgr.GetLoginUrl();
                    if (!string.IsNullOrWhiteSpace(m_loginUrl))
                    {
                        Response.Redirect(m_loginUrl, true);
                    }
                }
            }
            else
            {
                // windows authentication enabled...
                if (m_user.Identity.IsAuthenticated)
                {
                    string m_applicationName = cfgMgr.GetApplicationName();
                    string cnName = cfgMgr.GetConnectionStringName();

                    string[] m_roles = Roles.GetRolesForUser(m_username);

                    Pages.ApplicationName = m_applicationName;
                    Pages.ConnectionString = ConfigurationManager.ConnectionStrings[cnName].ConnectionString;
                    bool[] m_permissions = new bool[m_roles.Length];
                    for (int i = 0; i < m_roles.Length; i++)
                    {
                        m_permissions[i] = Pages.IsPageInRole(m_pageName, m_roles[i]);
                    }

                    if (this.Page.Master != null)
                    {
                        Label m_lblUserName = (Label)this.Page.Master.FindControl("lblUserLogged");
                        if (m_lblUserName != null)
                        {
                            m_lblUserName.Text = m_username;
                        }
                    }

                    if (!m_permissions.Contains(true))
                    {
                        Response.Redirect("~/403.aspx");
                    }
                }
                else
                {
                    Response.Redirect("~/403.aspx");
                }
            }

            base.OnPreInit(e);
        }

        protected override void Render(HtmlTextWriter writer)
        {
            const string CSSRULE = "applyrule";

            StringBuilder sb = new StringBuilder();
            StringWriter sw = new StringWriter(sb);
            HtmlTextWriter hWriter = new HtmlTextWriter(sw);
            base.Render(hWriter);

            // *** store to a string
            string PageResult = sb.ToString();

            //
            HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
            doc.LoadHtml(PageResult);

            var findclasses = doc.DocumentNode.Descendants().Where(d => d.Attributes.Contains("class") &&
                d.Attributes["class"].Value.Split(' ').Any(b => b.Equals(CSSRULE, StringComparison.InvariantCultureIgnoreCase))).ToList();
            if (findclasses != null && findclasses.Count() > 0)
            {
                ConfigurationManagerHelper cfgMgr = new ConfigurationManagerHelper();
                string m_applicationName = cfgMgr.GetApplicationName();
                string cnName = cfgMgr.GetConnectionStringName();

                GrayParrot.Web.Security.Controls.ApplicationName = m_applicationName;
                GrayParrot.Web.Security.Controls.ConnectionString = ConfigurationManager.ConnectionStrings[cnName].ConnectionString;

                string[] m_roles = Roles.GetRolesForUser(this.m_user.Identity.Name);

                for (int i = 0; i < findclasses.Count(); i++)
                {
                    string m_id = findclasses[i].Attributes["id"].Value;

                    ControlActions m_isControlToShow = ControlActions.Hidden;
                    foreach (string role in m_roles)
                    {
                        m_isControlToShow = (ControlActions)GrayParrot.Web.Security.Controls.IsControlInRoleEx(m_id, this.m_pageName, role);

                        if ((m_isControlToShow & ControlActions.Hidden) == ControlActions.Hidden)
                        {
                            findclasses[i].Remove();
                            break;
                        }

                        if ((m_isControlToShow & ControlActions.Readonly) == ControlActions.Readonly)
                        {
                            findclasses[i].Attributes.Add("readonly", "true");
                        }
                    }
                }
            }

            string m_pageMod = doc.DocumentNode.OuterHtml;

            //var sw2 = new StringWriter();
            //doc.Save(sw2);
            //var s = sw2.ToString();

            // *** Write it back to the server
            writer.Write(m_pageMod);
        }
    }
}
